package com.wlyuan.open.scanner.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wlyuan.open.scanner.dao.entity.BasicAreaDO;
import com.wlyuan.open.scanner.dao.entity.PriceDocDetailsDO;
import com.wlyuan.open.scanner.dao.entity.PriceDocIndexDO;
import com.wlyuan.open.scanner.dao.mapper.PriceDocDetailsMapper;
import com.wlyuan.open.scanner.dao.mapper.PriceDocIndexMapper;
import com.wlyuan.open.scanner.domain.quotation.QuotationDetail;
import com.wlyuan.open.scanner.domain.quotation.QuotationDetailConvert;
import com.wlyuan.open.scanner.domain.quotation.QuotationSurchargeFee;
import com.wlyuan.open.scanner.repository.BasicAreaRepository;
import com.wlyuan.open.scanner.repository.QuotationDetailRepository;
import com.wlyuan.open.scanner.utils.BatchSelectUtils;
import com.wlyuan.open.scanner.utils.StreamUtils;
import com.wlyuan.open.scanner.utils.enums.InvalidEnum;
import com.wlyuan.open.scanner.utils.enums.quotation.QuotationDetailTypeEnum;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class QuotationDetailRepositoryImpl implements QuotationDetailRepository {
    private final PriceDocDetailsMapper priceDocdetailsMapper;
    private final PriceDocIndexMapper priceDocindexMapper;
    private final BasicAreaRepository basicAreaRepository;

    @Override
    public List<QuotationDetail> getDetails(Long quotationId) {
        if (!LongUtils.notNullLong(quotationId)) {
            return Collections.emptyList();
        }
        var list = select(quotationId);
        process(list, true);
        return QuotationDetailConvert.convert(list);
    }

    @Override
    public List<QuotationDetail> getDetailsFee(Long quotationId) {
        if (!LongUtils.notNullLong(quotationId)) {
            return Collections.emptyList();
        }
        var list = select(quotationId);
        process(list, false);
        return QuotationDetailConvert.convert(list);
    }

    @Override
    public List<QuotationDetail> getDetailsByIds(List<Long> quotationIds) {
        if (CollectionUtils.isEmpty(quotationIds)) {
            return Collections.emptyList();
        }
        //分批查询
        var list = BatchSelectUtils.batch(quotationIds, this::select);
        process(list, false);
        return QuotationDetailConvert.convert(list);
    }

    @Override
    public List<QuotationDetail> getDetailsByDocIds(List<Long> quotationIds) {
        if (CollectionUtils.isEmpty(quotationIds)) {
            return Collections.emptyList();
        }
        //分批查询
        var list = BatchSelectUtils.batch(quotationIds, this::select);
        return QuotationDetailConvert.convert(list);
    }

    @Override
    public boolean getOrderQuotation(Long orderId) {
        //审核通过
        var list = priceDocindexMapper.getCheckByOrderId(orderId);
        return CollectionUtils.isEmpty(list);
    }

    @Override
    public QuotationSurchargeFee getSurchargeByOrderId(Long orderId) {
        //审核通过
        QuotationSurchargeFee fees = new QuotationSurchargeFee();
        var list = priceDocindexMapper.getCheckByOrderId(orderId);
        if (CollectionUtils.isEmpty(list)) {
            fees.setQuotation(false);
            return fees;
        }
        fees.setQuotation(true);
        var docId = list.stream().map(PriceDocIndexDO::getIndexId).collect(Collectors.toList());
        var priceList = getDetailsByDocIds(docId);
        if (CollectionUtils.isEmpty(priceList)) {
            return fees;
        }
        //报价附加费
        var price = Optional.ofNullable(priceList.stream().filter(x -> QuotationDetailTypeEnum.ADDITION.getValue().equals(x.getType()) && !LongUtils.notNullInteger(x.getAdditionType()))
                .findAny().orElse(null)).map(QuotationDetail::getPrice).orElse(BigDecimal.ZERO);
        fees.setQuoteSurchargeFee(price);
        //补充费用集合
        var additionList = priceList.stream().filter(x -> QuotationDetailTypeEnum.ADDITION.getValue().equals(x.getType()) && LongUtils.notNullInteger(x.getAdditionType())).collect(Collectors.toList());
        fees.setSurchargeFeeList(QuotationDetailConvert.convertSurcharge(additionList));
        return fees;
    }

    private void process(List<PriceDocDetailsDO> list, boolean address) {
        list.forEach(data -> {
            //零担，提货费，送货费，装货费，卸货费 最大值，最小值
            if (QuotationDetailTypeEnum.TEMPLATE_SPEC_TYPE.contains(data.getDetailType())) {
                //重量
                if (LongUtils.notNullLong(data.getDetailWeightunit())) {
                    data.setDetailUnit(data.getDetailWeightunit().intValue());
                    data.setMinValue(data.getDetailMinweight());
                    data.setMaxValue(data.getDetailMaxweight());
                }
                //体积
                if (LongUtils.notNullLong(data.getDetailVolumeunit())) {
                    data.setDetailUnit(data.getDetailVolumeunit().intValue());
                    data.setMinValue(data.getDetailMinvolume());
                    data.setMaxValue(data.getDetailMaxvolume());
                }
                //数量
                if (LongUtils.notNullLong(data.getDetailCountunit())) {
                    data.setDetailUnit(data.getDetailCountunit().intValue());
                    data.setMinValue(data.getDetailMincount());
                    data.setMaxValue(data.getDetailMaxcount());
                }
            }
            if (data.getDetailAmount() == null) {
                data.setDetailAmount(0.0);
            }
        });
        //地址信息
        if (address) {
            processAddress(list);
        }
    }

    @Override
    public Integer getQuotationType(Long quotationId) {
        return Optional.ofNullable(quotationId).map(id -> {
            var data = priceDocindexMapper.selectById(id);
            return Optional.ofNullable(data).map(PriceDocIndexDO::getIndexType).orElse(null);
        }).orElse(null);
    }

    private List<PriceDocDetailsDO> select(Long quotationId) {
        LambdaQueryWrapper<PriceDocDetailsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PriceDocDetailsDO::getDetailDocid, quotationId).eq(PriceDocDetailsDO::getDetailInvalid, InvalidEnum.ENABLE.getValue());

        var list = priceDocdetailsMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    private List<PriceDocDetailsDO> select(List<Long> quotationIds) {
        LambdaQueryWrapper<PriceDocDetailsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PriceDocDetailsDO::getDetailInvalid, InvalidEnum.ENABLE.getValue()).in(PriceDocDetailsDO::getDetailDocid, quotationIds);

        var list = priceDocdetailsMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    /**
     * 明细地址
     *
     * @param list
     */
    private void processAddress(List<PriceDocDetailsDO> list) {
        var areaMap = getAreaIds(list);
        list.forEach(data -> {
            Optional.ofNullable(areaMap.get(data.getDetailFromprovince())).ifPresent(fromProvince -> data.setFromProvinceName(fromProvince.getAreaName()));
            Optional.ofNullable(areaMap.get(data.getDetailFromcity())).ifPresent(fromCity -> data.setFromCityName(fromCity.getAreaName()));
            Optional.ofNullable(areaMap.get(data.getDetailFromdistrict())).ifPresent(fromDistrict -> data.setFromDistrictName(fromDistrict.getAreaName()));
            Optional.ofNullable(areaMap.get(data.getDetailToprovince())).ifPresent(toProvince -> data.setToProvinceName(toProvince.getAreaName()));
            Optional.ofNullable(areaMap.get(data.getDetailTocity())).ifPresent(toCity -> data.setToCityName(toCity.getAreaName()));
            Optional.ofNullable(areaMap.get(data.getDetailTodistrict())).ifPresent(toDistrict -> data.setToDistrictName(toDistrict.getAreaName()));
        });
    }

    /**
     * 地区信息
     *
     * @param list
     * @return
     */
    private Map<Long, BasicAreaDO> getAreaIds(List<PriceDocDetailsDO> list) {
        //省市区ID
        List<Long> fromProvince = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailFromprovince);
        List<Long> toProvince = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailToprovince);
        List<Long> fromCity = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailFromcity);
        List<Long> toCity = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailTocity);
        List<Long> fromDistrict = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailFromdistrict);
        List<Long> toDistrict = StreamUtils.mapList(list, PriceDocDetailsDO::getDetailTodistrict);
        return basicAreaRepository.getAreaMap(fromProvince, toProvince, fromCity, toCity, fromDistrict, toDistrict);
    }

}
